package com.glzn.springboot03.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.glzn.springboot03.entity.Event;
import com.glzn.springboot03.mapper.EventMapper;
import com.glzn.springboot03.mqtt.MqttPublishClient;
import com.glzn.springboot03.service.EventService;
import com.glzn.springboot03.util.ComService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * @author gongjq
 */
@Service
public class EventServiceImpl implements EventService {
	private final static Logger logger = LoggerFactory.getLogger(EventServiceImpl.class);

	private Map<String, Integer> map = new HashMap<>();

	@Autowired
	private EventMapper eventMapper;

	@Override
	public List<Event> findAll(Integer deviceId) {
		return eventMapper.findAll(deviceId);
	}

	@Override
	public PageInfo<Event> findByType(String type, int pageNum, int pageSize, Integer deviceId) {
		Page<Event> page = PageHelper.startPage(pageNum, pageSize);
		if (type == null){
			eventMapper.findAll(deviceId);
		}else {
			eventMapper.findByType(type, deviceId);
		}
		return new PageInfo<>(page);
	}

	@Override
	public List<Event> findByTime(Date startTime, Date endTime, Integer deviceId) {
		return eventMapper.findByTime(startTime,endTime, deviceId);
	}

	@Override
	public PageInfo<Event> findByTime(Date startTime, Date endTime, int pageNum, int pageSize, Integer deviceId) {
		Page<Event> page = PageHelper.startPage(pageNum, pageSize);
		if (endTime.compareTo(startTime) >= 0){
			eventMapper.findByTime(startTime,endTime,deviceId);
		}
		return new PageInfo<>(page);
	}

	@Override
	public PageInfo<Event> findByTimeAndType(Date startTime, Date endTime, String type, int pageNum, int pageSize, Integer deviceId) {
		Page<Event> page = PageHelper.startPage(pageNum, pageSize);
		eventMapper.findByTimeAndType(startTime, endTime, type, deviceId);
		return new PageInfo<>(page);
	}

	@Override
	public List<Event> findByTimeAndType(Date startTime, Date endTime, String type, Integer deviceId) {
		return eventMapper.findByTimeAndType(startTime, endTime, type, deviceId);
	}

	@Override
	public Boolean insert(Event event) {
		eventMapper.insert(event);
		return true;
	}

	@Override
	public boolean deleteAll(Integer deviceId) {
		return eventMapper.deleteAll(deviceId);
	}

	@Override
	public int getProcess(String sessionId) {
		Integer process = map.get(sessionId);
		if (process == null) {
			process = 0;
		}
		if (process == 100) {
			map.remove(sessionId);
		}
		return process;
	}

	@Override
	public String listEvent() throws UnsupportedEncodingException {
		HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
		MqttPublishClient mqttPublishClient = (MqttPublishClient) session.getAttribute("mqttPublishClient");
		Integer deviceId = (Integer) session.getAttribute("device_id");
		String sessionId = session.getId();

		if (mqttPublishClient == null) {
			return "device";
		}
		int process = 0;
		ComService comService = new ComService();
		comService.setServerType(0x2);
		comService.setCmd(0x40);
		System.out.println(Thread.currentThread().getId()+"在获取数据...mqtt id:"+mqttPublishClient.getMqtt().getId());
		byte[] data = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
		if(null == data){
			return "failed";
		}
		//3、将数据组成Event List
		List<Event> eventList =  new ArrayList<>();
		int nPos = 8;
		int startIndex = 0;
		int eventTypeCount = data[7];
		//获取事件
		for (int i = 0; i < eventTypeCount; i++) {
			startIndex = 0;
			int eventNum = data[nPos++];
			int eventCout = (data[nPos + 1] & 0xFF)<< 8 | data[nPos]&0xFF;
			nPos += 2;

			if (eventCout == 0) {
				continue;
			}

			do {
				int nPos2 = 8;
				comService.setServerType(0x2);
				comService.setCmd(0x41);
				comService.setEventType((byte) i);
				comService.setEventStartIndex(startIndex);

				byte[] data1 = mqttPublishClient.sendAndRecv(comService, 1000*20, false);
				int errTimes = 0;
				while (data1 == null) {
					data1 = mqttPublishClient.sendAndRecv(comService, 1000 * 20, true);
					errTimes++;
					if(errTimes > 3) {
						return "failed";
					}
				}
				/*
				解析事件
				一帧中的事件总数
				*/
				int count = data1[nPos2++];
				if (count == 0){
					process = (1 + i)*100/eventTypeCount;
					map.put(sessionId, process);
					break;
				}
				for (int j = 0; j < count; j++) {
					int eventLength = data1[nPos2++];
					int year = 100+data1[nPos2++];
					int month = data1[nPos2++];
					int day = data1[nPos2++];
					int hrs = data1[nPos2++];
					int min = data1[nPos2++];
					int sec = data1[nPos2++];
					int millsecond = ((data1[nPos2 + 1] & 0xFF) << 8) | (data1[nPos2]&0xFF);
					nPos2+=2;

					Date date = new Date(year, month - 1, day, hrs, min, sec);
					logger.debug("date:{}", date);
					//类型
					int len = data1[nPos2++];
					String type = new String(data1, nPos2, len, "gbk");
					type = type.replaceAll("\u0000","");
					logger.debug("type:{}", type);
					nPos2 += len;
					//名称
					len = data1[nPos2++];
					String name = new String(data1, nPos2, len, "gbk");
					name = name.replaceAll("\u0000","");
					logger.debug("name:{}", name);
					nPos2 += len;
					//扩展
					len = data1[nPos2++];
					String extend = new String(data1, nPos2, len, "gbk");
					extend = extend.replaceAll("\u0000","");
					logger.debug("extend:{}", extend);
					nPos2 += len;
					Event event = new Event(startIndex, name, type, extend, date, millsecond, deviceId);
					eventList.add(event);
					logger.debug("event:{}", event);
					startIndex++;
					logger.debug("startIndex:{}", startIndex);
					//进度
					process = 100*startIndex/eventCout/eventTypeCount+i*100/eventTypeCount;
					map.put(sessionId, process);
				}
				logger.info("i:{}", i);
			} while (startIndex < eventCout);
		}
		//4、将Event放到数据库
		deleteAll(deviceId);
		for (Event event : eventList) {
			insert(event);
		}
		process = 100;
		map.put(sessionId, process);
		//5、返回结果
		return "success";
	}
}
